package com.star95.springbooti18n.exception;

import com.google.common.collect.Lists;
import com.star95.springbooti18n.dto.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

/**
 * 异常处理器
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理自定义业务异常
     */
    @ExceptionHandler(BusinessException.class)
    public Result<?> handleServiceException(BusinessException e) {
        log.error(e.getMessage(), e);
        return Result.error(e.getMessage());
    }

    /**
     * 处理对象类型参数校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List<String> errors = Lists.newArrayList();
        for (FieldError error : fieldErrors) {
            errors.add(error.getDefaultMessage());
        }
        String error = StringUtils.join(errors, " | ");
        log.info("MethodArgumentNotValidException:{}", error);
        return Result.error(error);
    }

    /**
     * 处理基础类型参数校验异常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result handleConstraintViolationException(ConstraintViolationException ex) {
        Set<ConstraintViolation<?>> ConstraintViolations = ex.getConstraintViolations();
        List<String> errors = Lists.newArrayList();
        for (ConstraintViolation constraint : ConstraintViolations) {
            errors.add(constraint.getMessage());
        }
        String errorMsg = StringUtils.join(errors, " | ");
        log.info("ConstraintViolationException:{}", errorMsg);
        return Result.error(errorMsg);
    }

    /**
     * 处理顶层异常Exception
     *
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public Result<?> handleException(Exception e) {
        log.error(e.getMessage(), e);
        return Result.error(e.getMessage());
    }
}
